package nacos

import (
	"context"
	"fmt"
	"gitee.com/vrv_media/go-micro-framework/pkg/common/util/net"
	log "gitee.com/vrv_media/go-micro-framework/pkg/logger"
	"gitee.com/vrv_media/go-micro-framework/registry"
	regOps "gitee.com/vrv_media/go-micro-framework/registry/options"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

type NacosDiscovery struct {
	//prefix  string
	//weight  float64
	cluster string
	group   string
	kind    string
	cli     naming_client.INamingClient
}

func NewNacosDiscovery(options *regOps.DiscoveryOptions) *NacosDiscovery {
	host, port, err := net.ExtractHostPort(options.Address)
	if err != nil {
		log.ErrorF("split host and port error: %v", err)
		panic(err)
	}
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(host, port),
	}
	cc := constant.ClientConfig{
		NamespaceId:         "public", // namespace id
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		LogLevel:            "debug",
	}
	// a more graceful way to create naming client
	client, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &cc,
			ServerConfigs: sc,
		},
	)
	if err != nil {
		log.ErrorF("create naming client failed.error=%v", err.Error())
		panic(err)
	}
	return &NacosDiscovery{
		cluster: "DEFAULT",
		group:   constant.DEFAULT_GROUP,
		kind:    "grpc",
		cli:     client,
	}
}

// GetService return the service instances in memory according to the service name.
func (d *NacosDiscovery) GetService(_ context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
	res, err := d.cli.SelectInstances(vo.SelectInstancesParam{
		ServiceName: serviceName,
		GroupName:   d.group,
		HealthyOnly: true,
	})
	if err != nil {
		return nil, err
	}
	items := make([]*registry.ServiceInstance, 0, len(res))
	for _, in := range res {
		kind := d.kind
		if k, ok := in.Metadata["kind"]; ok {
			kind = k
		}
		items = append(items, &registry.ServiceInstance{
			ID:        in.InstanceId,
			Name:      in.ServiceName,
			Version:   in.Metadata["version"],
			Metadata:  in.Metadata,
			Endpoints: []string{fmt.Sprintf("%s://%s:%d", kind, in.Ip, in.Port)},
		})
	}
	return items, nil
}

// Watch creates a watcher according to the service name.
func (d *NacosDiscovery) Watch(ctx context.Context, serviceName string) (registry.Watcher, error) {
	return newWatcher(ctx, d.cli, serviceName, d.group, d.kind, []string{d.cluster})
}
